#pragma once
#define THREADPOOL_H 
#ifdef THREADPOOL_H

#include <vector>
#include <iostream>
#include <queue>
#include <memory>
#include <atomic>
#include <functional>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <unordered_map>

enum class PoolMode     // 线程池模式
{
    MODE_FIXED,     // 固定数量
    MODE_CACHED     // 动态增长
};

/* 信号量 */
class Semaphore     
{
public:
    Semaphore(size_t resLimit = 0) : resLimit_(resLimit) {}
    ~Semaphore() = default;

    void wait()
    {
        std::unique_lock<std::mutex> lock(mtx_);
        cond_.wait(lock, [&]()->bool { return resLimit_ > 0; });
        resLimit_--;
    }

    void post()
    {
        std::unique_lock<std::mutex> lock(mtx_);
        resLimit_++;
        cond_.notify_all();
    }
private:
    size_t resLimit_;
    std::mutex mtx_;
    std::condition_variable cond_;
};

/* Any类型，用于接收任意数据类型 */
class Any 
{
public:
    Any() = default;
    ~Any() = default;
    Any(const Any&) = delete;
    Any& operator=(const Any&) = delete;
    Any(Any&&) = default;
    Any& operator=(Any&&) = default;

    template<class T>
    Any(T data) : base_(std::make_unique<Derive<T>>(data)) {}   // 接收任意数据类型

    // 将数据提取为指定的数据类型
    template<class T>
    T cast_()
    {
        Derive<T>* pd = dynamic_cast<Derive<T>*>(base_.get());      // base* -> Derive*
        if(pd == nullptr)
        {
            throw "type is unmatch!";
        } 
        return pd->data_;
    }

private:
    class Base
    {
    public: 
        virtual ~Base() = default;
    };
    template<class T>
    class Derive : public Base
    {
    public:
        Derive(T data) : data_(data) {}
        T data_;
    };
private:
    std::unique_ptr<Base> base_;
};

class Task;

/* 线程执行完任务后的返回值 */
class Result
{
public:
    Result(std::shared_ptr<Task> task, bool isValid = true);
    ~Result() = default;

    void setRetVal(Any any);    // 设置返回值
    Any get();               // 获取返回值
private:
    Any any_;   // 存储任务的返回值
    Semaphore sem_;     // 线程通信所需的信号量    
    std::shared_ptr<Task> task_;    // 指向该返回值对应的任务对象
    std::atomic_bool isValid_;      // 返回值的有效性
};


class Task
{
public:
    // virtual void run() = 0;
    virtual Any run() = 0;
    void exec();
    void setResult(Result* res);
private:
    Result* result_;
};

class Thread
{
public:
    using ThreadFunc = std::function<void(int)>;
    Thread(ThreadFunc func);
    ~Thread();
    void start();   // 启动线程
    int getId() const;
private:
    ThreadFunc func_;
    static int generateId_;
    int threadId_;  
};

class ThreadPool
{
public:
    ThreadPool();
    ~ThreadPool();

    void setMode(PoolMode mode);    // 设置线程池工作模式

    void setThreadSizeThreshHold(size_t threshhold);    // Cache模式上限阈值

    void setTaskQueMaxThreshHold(size_t threshhold);    // 设置任务队列阈值

    Result submitTask(std::shared_ptr<Task> sp);  // 提交任务

    void start(size_t initThreadSize = std::thread::hardware_concurrency());   // 启动线程池

    ThreadPool(const ThreadPool&) = delete;
    ThreadPool& operator=(const ThreadPool&) = delete; 
private:
    void threadFunc(int threadId);
    bool checkRunningState() const;
private:
    // std::vector<std::unique_ptr<Thread>> threads_;      // RAII管理内存
    std::unordered_map<int, std::unique_ptr<Thread>> threads_;
    size_t initThreadSize_;         // 线程数量
    size_t threadSizeThreshHold_;   // 线程数量上限阈值
    std::atomic_int curThreadSize_;     // 当前数量
    std::atomic_int idleThreadSize_;    // 空闲线程数量

    std::queue<std::shared_ptr<Task>> taskQue_;     // 任务队列
    std::atomic_uint taskSize_;      // 任务数量
    size_t taskQueMaxThreshHold_;    // 任务数量上限阈值

    std::mutex taskQueMtx_;     // 保证任务队列的线程安全
    std::condition_variable notFull_;   // 表任务队列不满
    std::condition_variable notEmpty_;  // 表任务队列不空
    std::condition_variable exitCond_;  // 等待线程资源回收

    PoolMode poolMode_;
    std::atomic_bool isRunning_;        // 线程池状态
};

#endif
